//1.引入Vue
import Vue from "vue";

//2.引入VueRouter
import VueRouter from "vue-router";

//引入vuex拿到token和请求用户名的方法
import store from "@/store";

//使用路由懒加载引入组件
const Home = () => import("@pages/Home");
const Search = () => import("@pages/Search");
const Login = () => import("@pages/Login");
const Register = () => import("@pages/Register");
const Detail = () => import("@pages/Detail");
const AddCartSuccess = () => import("@pages/AddCartSuccess");
const ShopCart = () => import("@pages/ShopCart");
const Trade = () => import("@pages/Trade");
const Pay = () => import("@pages/Pay");
const PaySuccess = () => import("@pages/PaySuccess");
const Center = () => import("@pages/Center");
const mayOrder = () => import("@pages/Center/mayOrder");
const TeamOrder = () => import("@pages/Center/TeamOrder");

//3.使用VueRouter
Vue.use(VueRouter);


//重写路由的push方法:
//1.先获取原始的push方法,供自定义push中使用
const lastPush = VueRouter.prototype.push

//2.重写push , 给第二第三个参数传入默认的函数  , 返回原来的push方法参数中就有了这两个函数 , 就可以处理异常了
VueRouter.prototype.push = function(location , onComplete=()=>{}  ,onAbort=()=>{}){
  /* 
    因为之前的push在VueRouter的原型对象上放,所以原本的push中this就是指向VueRouter的实例
    但是现在lastPush被直接默认调用,所以this就指向了undefined了,内部很可能出错
    我们在调用lastPush的时候,可以改变他的this指向VueRouter的实例
  */
  return lastPush.call(this , location , onComplete , onAbort)
}




//4.创建路由器对象并暴露
const router =  new VueRouter({
  mode: "history",
  //滚动行为
  scrollBehavior () {
    // return 期望滚动到哪个的位置
    return {
      x:0,
      y:0
    }
  },
  routes: [
    {
      path: "/home",
      component: Home,
      name: "home",
    },
    {
      path: "/search/:keyword?",
      component: Search,
      name: "search",
    },
    {
      path: "/login",
      component: Login,
      name: "login",
      //登录路由隐藏Footer组件
      meta:{isFooterHidden: true},
      //路由独享守卫，判断如果是登录状态则不能进登录路由
      beforeEnter(to , from , next){
        if(store.state.user.token){
          next("/")
        }else{
          next()
        }
      }
    },
    {
      path: "/register",
      component: Register,
      name: "register",
      //注册路由隐藏Footer组件
      meta:{isFooterHidden: true}
    },
    {
      path: "/detail/:skuId",
      component: Detail,
      name: "detail",
    },
    {
      path: "/addCartSuccess",
      component: AddCartSuccess,
      name: "addCartSuccess",
      //路由独享守卫，限制只有临时存储(添加购物车成功创建临时存储)才能进添加购物车成功这个路由
      beforeEnter(to, from , next){
        if(sessionStorage.getItem("cartData")){
          next()
        }else{
          next("/shopCart")
        }
      }
    },
    {
      path: "/trade",
      component: Trade,
      name: "trade",
      beforeEnter: (to, from, next) => {
        if(from.path.startsWith("/shopCart")){
          next()
        }else{
          next("/shopCart")
        }
      }
    },
    {
      path: "/pay",
      component: Pay,
      name: "pay",
      beforeEnter: (to, from, next) => {
        if(from.path.startsWith("/trade")){
          next()
        }else{
          next("/shopCart")
        }
      }
    },
    {
      path: "/paysuccess",
      component: PaySuccess,
      name: "paysuccess",
      beforeEnter: (to, from, next) => {
        if(from.path.startsWith("/pay")){
          next()
        }else{
          next("/shopCart")
        }
      }
    },
    {
      path: "/center",
      component: Center,
      name: "center",
      children:[
        {path: "mayorder" , component: mayOrder , name: "mayorder"},
        {path: "teamorder" , component: TeamOrder , name: "teamorder"},
        {path: "" , redirect: "/center/mayorder"}
      ],
      beforeEnter: (to, from, next) => {
        if(from.path.startsWith("/paysuccess")){
          next()
        }else{
          next("/shopCart")
        }
      }
    },
    {
      path: "/shopCart",
      component: ShopCart,
      name: "shopCart",
    },
    {
      path: "/",
      redirect: "/home",
    },
  ],
});


/* 
  token校验逻辑:(目的:判断是否登录,并且登录后想要用户名)
    - 完成登录逻辑,拿到token,保存起来
    - 确定哪些页面需要token才能进入,哪些页面不需要token就可以进入
    - 因为每次进入路由前都要进行校验,所以我们选用全局前置守卫

    - 首先判断用户名是否存在,如果存在,则说明用户肯定是登录状态,并且我们也拥有的用户名,则直接放行

    - 在判断当前要去的路由是否是需要登录(token)的,然后再进行下一步操作
      - 如果当前的要去的路由地址不需要登录,则直接放行...
      - 如果当前的要去的路由地址需要登录,则检测是否拥有token
        - 如果拥有token,则获取一下用户名,并放行 
        - 如果没有token直接去登录页登陆以后,再来访问当前路由
*/

router.beforeEach( async (to , from , next) => {
  //使用一个数组,保存所有必须有token才能访问的路由地址
  const checkPath = ["/center", "/pay", "/paysuccess", "/trade", "/shopCart"];

  //判断当前要去的地址是否需要token校验
  const isCheckPath = checkPath.some((item) => {
    //判断要去的地址是否以item为开头(考虑多级路由)
    return to.path.startsWith(item)
  })

  //获取vuex中的token和用户名
  const token = store.state.user.token;
  const nickeName = store.state.user.nickeName;

  //判断有用户说明一定是登录状态直接放行
  if(nickeName){
    return next()
  }
    
  //走到这里说明没有用户名 判断是否需要校验token
  if(isCheckPath){
    //当前路径需要token校验
    //首先判断是否拥有token
    if(token){
     //如果有token,则获取一下用户名,并放行
     try {
      //dispatch方法的返回值就是这个actions方法的返回值
      await store.dispatch("user/getUserName");
      next();
    } catch (e) {
      //token失效dispatch就返回失败的promise实例，就会进到这个异常处理，则直接返回到login页面
      next("/login");
    }
    }else{
      //如果没有token则直接去登录页登录
      next("/login");
    }

  }else{
    //当前路由不需要token校验(但是如果此时你是有token的,我们可以顺便获取一下用户名) 
    //如果有token,则获取一下用户名,并放行
    if(token){
      try {
        //dispatch方法的返回值就是这个actions方法的返回值
        await store.dispatch("user/getUserName");
        next();
      } catch (e) {
        //token失效dispatch就返回失败的promise实例，就会进到这个异常处理，则直接返回到login页面
        next("/login");
      }
    }
    next();
  }
    
  
})

export default router
